home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / io / PushbackInputStream.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  10.4 KB  |  316 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)PushbackInputStream.java    1.25 98/04/30
  3.  *
  4.  * Copyright 1994-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.io;
  16.  
  17. /**
  18.  * A <code>PushbackInputStream</code> adds
  19.  * functionality to another input stream, namely
  20.  * the  ability to "push back" or "unread"
  21.  * one byte. This is useful in situations where
  22.  * it is  convenient for a fragment of code
  23.  * to read an indefinite number of data bytes
  24.  * that  are delimited by a particular byte
  25.  * value; after reading the terminating byte,
  26.  * the  code fragment can "unread" it, so that
  27.  * the next read operation on the input stream
  28.  * will reread the byte that was pushed back.
  29.  * For example, bytes representing the  characters
  30.  * constituting an identifier might be terminated
  31.  * by a byte representing an  operator character;
  32.  * a method whose job is to read just an identifier
  33.  * can read until it  sees the operator and
  34.  * then push the operator back to be re-read.
  35.  *
  36.  * @author  David Connelly
  37.  * @author  Jonathan Payne
  38.  * @version 1.25, 04/30/98
  39.  * @since   JDK1.0
  40.  */
  41. public
  42. class PushbackInputStream extends FilterInputStream {
  43.     /**
  44.      * The pushback buffer.
  45.      * @since   JDK1.1
  46.      */
  47.     protected byte[] buf;
  48.  
  49.     /**
  50.      * The position within the pushback buffer from which the next byte will
  51.      * be read.  When the buffer is empty, <code>pos</code> is equal to
  52.      * <code>buf.length</code>; when the buffer is full, <code>pos</code> is
  53.      * equal to zero.
  54.      *
  55.      * @since   JDK1.1
  56.      */
  57.     protected int pos;
  58.  
  59.     /**
  60.      * Check to make sure that this stream has not been closed
  61.      */
  62.     private void ensureOpen() throws IOException {
  63.     if (in == null)
  64.         throw new IOException("Stream closed");
  65.     }
  66.  
  67.     /**
  68.      * Creates a <code>PushbackInputStream</code>
  69.      * with a pushback buffer of the specified <code>size</code>,
  70.      * and saves its  argument, the input stream
  71.      * <code>in</code>, for later use. Initially,
  72.      * there is no pushed-back byte  (the field
  73.      * <code>pushBack</code> is initialized to
  74.      * <code>-1</code>).
  75.      *
  76.      * @param  in    the input stream from which bytes will be read.
  77.      * @param  size  the size of the pushback buffer.
  78.      * @exception IllegalArgumentException if size is <= 0
  79.      * @since  JDK1.1
  80.      */
  81.     public PushbackInputStream(InputStream in, int size) {
  82.     super(in);
  83.         if (size <= 0) {
  84.             throw new IllegalArgumentException("size <= 0");
  85.         }
  86.     this.buf = new byte[size];
  87.     this.pos = size;
  88.     }
  89.  
  90.     /**
  91.      * Creates a <code>PushbackInputStream</code>
  92.      * and saves its  argument, the input stream
  93.      * <code>in</code>, for later use. Initially,
  94.      * there is no pushed-back byte  (the field
  95.      * <code>pushBack</code> is initialized to
  96.      * <code>-1</code>).
  97.      *
  98.      * @param   in   the input stream from which bytes will be read.
  99.      */
  100.     public PushbackInputStream(InputStream in) {
  101.     this(in, 1);
  102.     }
  103.  
  104.     /**
  105.      * Reads the next byte of data from this input stream. The value 
  106.      * byte is returned as an <code>int</code> in the range 
  107.      * <code>0</code> to <code>255</code>. If no byte is available 
  108.      * because the end of the stream has been reached, the value 
  109.      * <code>-1</code> is returned. This method blocks until input data 
  110.      * is available, the end of the stream is detected, or an exception 
  111.      * is thrown. 
  112.      *
  113.      * <p> This method returns the most recently pushed-back byte, if there is
  114.      * one, and otherwise calls the <code>read</code> method of its underlying
  115.      * input stream and returns whatever value that method returns.
  116.      *
  117.      * @return     the next byte of data, or <code>-1</code> if the end of the
  118.      *             stream has been reached.
  119.      * @exception  IOException  if an I/O error occurs.
  120.      * @see        java.io.InputStream#read()
  121.      */
  122.     public int read() throws IOException {
  123.         ensureOpen();
  124.     if (pos < buf.length) {
  125.         return buf[pos++] & 0xff;
  126.     }
  127.     return super.read();
  128.     }
  129.  
  130.     /**
  131.      * Reads up to <code>len</code> bytes of data from this input stream into
  132.      * an array of bytes.  This method first reads any pushed-back bytes; after
  133.      * that, if fewer than than <code>len</code> bytes have been read then it
  134.      * reads from the underlying input stream.  This method blocks until at
  135.      * least 1 byte of input is available.
  136.      *
  137.      * @param      b     the buffer into which the data is read.
  138.      * @param      off   the start offset of the data.
  139.      * @param      len   the maximum number of bytes read.
  140.      * @return     the total number of bytes read into the buffer, or
  141.      *             <code>-1</code> if there is no more data because the end of
  142.      *             the stream has been reached.
  143.      * @exception  IOException  if an I/O error occurs.
  144.      * @see        java.io.InputStream#read(byte[], int, int)
  145.      */
  146.     public int read(byte[] b, int off, int len) throws IOException {
  147.         ensureOpen();
  148.         if ((off < 0) || (off > b.length) || (len < 0) ||
  149.             ((off + len) > b.length) || ((off + len) < 0)) {
  150.             throw new IndexOutOfBoundsException();
  151.         }
  152.  
  153.     if (len == 0) {
  154.         return 0;
  155.     }
  156.  
  157.     int avail = buf.length - pos;
  158.     if (avail > 0) {
  159.         if (len < avail) {
  160.         avail = len;
  161.         }
  162.         System.arraycopy(buf, pos, b, off, avail);
  163.         pos += avail;
  164.         off += avail;
  165.         len -= avail;
  166.     }
  167.     if (len > 0) {
  168.         len = super.read(b, off, len);
  169.         if (len == -1) {
  170.         return avail == 0 ? -1 : avail;
  171.         }
  172.         return avail + len;
  173.     }
  174.     return avail;
  175.     }
  176.  
  177.     /**
  178.      * Pushes back a byte by copying it to the front of the pushback buffer.
  179.      * After this method returns, the next byte to be read will have the value
  180.      * <code>(byte)b</code>.
  181.      *
  182.      * @param      b   the <code>int</code> value whose low-order 
  183.      *             byte is to be pushed back.
  184.      * @exception IOException If there is not enough room in the pushback
  185.      *                  buffer for the byte.
  186.      */
  187.     public void unread(int b) throws IOException {
  188.         ensureOpen();
  189.     if (pos == 0) {
  190.         throw new IOException("Push back buffer is full");
  191.     }
  192.     buf[--pos] = (byte)b;
  193.     }
  194.  
  195.     /**
  196.      * Pushes back a portion of an array of bytes by copying it to the front
  197.      * of the pushback buffer.  After this method returns, the next byte to be
  198.      * read will have the value <code>b[off]</code>, the byte after that will
  199.      * have the value <code>b[off+1]</code>, and so forth.
  200.      *
  201.      * @param b the byte array to push back.
  202.      * @param off the start offset of the data.
  203.      * @param len the number of bytes to push back.
  204.      * @exception IOException If there is not enough room in the pushback
  205.      *                  buffer for the specified number of bytes.
  206.      * @since     JDK1.1
  207.      */
  208.     public void unread(byte[] b, int off, int len) throws IOException {
  209.         ensureOpen();
  210.     if (len > pos) {
  211.         throw new IOException("Push back buffer is full");
  212.     }
  213.     pos -= len;
  214.     System.arraycopy(b, off, buf, pos, len);
  215.     }
  216.  
  217.     /**
  218.      * Pushes back an array of bytes by copying it to the front of the
  219.      * pushback buffer.  After this method returns, the next byte to be read
  220.      * will have the value <code>b[0]</code>, the byte after that will have the
  221.      * value <code>b[1]</code>, and so forth.
  222.      *
  223.      * @param b the byte array to push back
  224.      * @exception IOException If there is not enough room in the pushback
  225.      *                  buffer for the specified number of bytes.
  226.      * @since     JDK1.1
  227.      */
  228.     public void unread(byte[] b) throws IOException {
  229.     unread(b, 0, b.length);
  230.     }
  231.  
  232.     /**
  233.      * Returns the number of bytes that can be read from this input stream
  234.      * without blocking.  This method calls the <code>available</code> method
  235.      * of the underlying input stream; it returns that value plus the number of
  236.      * bytes that have been pushed back.
  237.      *
  238.      * @return     the number of bytes that can be read from the input stream
  239.      *             without blocking.
  240.      * @exception  IOException  if an I/O error occurs.
  241.      * @see        java.io.FilterInputStream#in
  242.      * @see        java.io.InputStream#available()
  243.      */
  244.     public int available() throws IOException {
  245.         ensureOpen();
  246.     return (buf.length - pos) + super.available();
  247.     }
  248.  
  249.     /**
  250.      * Skips over and discards <code>n</code> bytes of data from this 
  251.      * input stream. The <code>skip</code> method may, for a variety of 
  252.      * reasons, end up skipping over some smaller number of bytes, 
  253.      * possibly zero.  If <code>n</code> is negative, no bytes are skipped.
  254.      * 
  255.      * <p> The <code>skip</code> method of <code>PushbackInputStream</code>
  256.      * first skips over the bytes in the pushback buffer, if any.  It then
  257.      * calls the <code>skip</code> method of the underlying input stream if
  258.      * more bytes need to be skipped.  The actual number of bytes skipped
  259.      * is returned.
  260.      *
  261.      * @param      n   the number of bytes to be skipped.
  262.      * @return     the actual number of bytes skipped.
  263.      * @exception  IOException  if an I/O error occurs.
  264.      * @see        java.io.FilterInputStream#in
  265.      * @see        java.io.InputStream#skip(long n)
  266.      * @since      JDK1.2
  267.      */
  268.     public long skip(long n) throws IOException {
  269.         ensureOpen();
  270.     if (n <= 0) {
  271.         return 0;
  272.     }
  273.  
  274.     long pskip = buf.length - pos;
  275.     if (pskip > 0) {
  276.         if (n < pskip) {
  277.         pskip = n;
  278.         }
  279.         pos += pskip;
  280.         n -= pskip;
  281.     }
  282.     if (n > 0) {
  283.         pskip += super.skip(n);
  284.     }
  285.     return pskip;
  286.     }
  287.  
  288.     /**
  289.      * Tests if this input stream supports the <code>mark</code> and
  290.      * <code>reset</code> methods, which it does not.
  291.      *
  292.      * @return   <code>false</code>, since this class does not support the
  293.      *           <code>mark</code> and <code>reset</code> methods.
  294.      * @see     java.io.InputStream#mark(int)
  295.      * @see     java.io.InputStream#reset()
  296.      */
  297.     public boolean markSupported() {
  298.     return false;
  299.     }
  300.  
  301.     /**
  302.      * Closes this input stream and releases any system resources 
  303.      * associated with the stream. 
  304.      *
  305.      * @exception  IOException  if an I/O error occurs.
  306.      */
  307.     public synchronized void close() throws IOException {
  308.         if (in == null)
  309.             return;
  310.         in.close();
  311.         in = null;
  312.         buf = null;
  313.     }
  314.  
  315. }
  316.